#include "IST8310.h"
#include "drv_gpio.h"
#include "rttypes.h"
#include <rtthread.h>
#include <rtdevice.h>

#define LOG_TAG              "ist8310"
#define LOG_LVL              LOG_LVL_DBG
#include <ulog.h>

#define IST8310_I2C_ADDR          0x0E
#define IST8310_I2C_BUS_NAME      "hwi2c3"  /* 传感器连接的I2C总线设备名称(硬件i2c) */
static struct rt_i2c_bus_device *i2c3_bus = RT_NULL;     /* I2C总线设备句柄 */
#define IST8310_RESET_PIN GET_PIN(G,6)

static ist8310_data_t ist8310_data;

#define MAG_SEN 0.3f //raw int16 data change to uT unit. 原始整型数据变成 单位ut

#define IST8310_WHO_AM_I 0x00       //ist8310 "who am I " 
#define IST8310_WHO_AM_I_VALUE 0x10 //device ID
#define IST8310_WRITE_REG_NUM 3 
#define IST8310_DATA_REG 0x03       // ist8310的数据寄存器
#define IST8310_WHO_AM_I 0x00       // ist8310 id 寄存器值


// the first column:the registers of IST8310. 第一列:IST8310的寄存器
// the second column: the value to be writed to the registers.第二列:需要写入的寄存器值
// the third column: return error value.第三列:返回的错误码
static uint8_t ist8310_write_reg_data_error[IST8310_WRITE_REG_NUM][3] = {
    {0x0B, 0x08, 0x01},  // enalbe interrupt  and low pin polarity.开启中断，并且设置低电平
    {0x41, 0x12, 0x02},  // average 4 times.平均采样四次
    //{0x42, 0xC0, 0x03},  // must be 0xC0. 必须是0xC0
    {0x0A, 0x0B, 0x04}}; // 200Hz output rate.200Hz输出频率


/* 写传感器寄存器 */
static void rt_i2c_write_reg(uint16_t addr, uint16_t reg, uint8_t *data, uint16_t len)
{
    rt_uint8_t tmp = reg;
    struct rt_i2c_msg msgs[2];

    msgs[0].addr  = addr;             /* Slave address */
    msgs[0].flags = RT_I2C_WR;        /* Write flag */
    msgs[0].buf   = &tmp;             /* Slave register address */
    msgs[0].len   = 1;                /* Number of bytes sent */

    msgs[1].addr  = addr;             /* Slave address */
    msgs[1].flags = RT_I2C_WR | RT_I2C_NO_START;        /* Read flag */
    msgs[1].buf   = data;             /* Read data pointer */
    msgs[1].len   = len;              /* Number of bytes read */

    if (rt_i2c_transfer(i2c3_bus, msgs, 2) != 2)
    {
        LOG_E("device:%d write reg:%d data:%d error!\n",IST8310_I2C_ADDR,addr,reg);
    }
}

static void rt_i2c_read_reg(uint16_t addr, uint16_t reg, uint8_t *data, uint16_t len)
{
    rt_uint8_t tmp = reg;
    struct rt_i2c_msg msgs[2];

    msgs[0].addr  = addr;             /* Slave address */
    msgs[0].flags = RT_I2C_WR;        /* Write flag */
    msgs[0].buf   = &tmp;             /* Slave register address */
    msgs[0].len   = 1;                /* Number of bytes sent */

    msgs[1].addr  = addr;             /* Slave address */
    msgs[1].flags = RT_I2C_RD;        /* Read flag */
    msgs[1].buf   = data;             /* Read data pointer */
    msgs[1].len   = len;              /* Number of bytes read */

    if (rt_i2c_transfer(i2c3_bus, msgs, 2) != 2)
    {
        LOG_E("device:%d read reg:%d data:%d error!\n",IST8310_I2C_ADDR,addr,reg);
    }
}


void ReadIST8310Data(ist8310_data_t* meg_data) {
    uint8_t buf[6];
    int16_t temp_ist8310_data = 0;
    rt_i2c_read_reg(IST8310_I2C_ADDR,IST8310_DATA_REG,buf,6);
    temp_ist8310_data = (int16_t)((buf[1] << 8) | buf[0]);
    meg_data->raw_data.x = MAG_SEN * temp_ist8310_data;
    temp_ist8310_data = (int16_t)((buf[3] << 8) | buf[2]);
    meg_data->raw_data.y = MAG_SEN * temp_ist8310_data;
    temp_ist8310_data = (int16_t)((buf[5] << 8) | buf[4]);
    meg_data->raw_data.z= MAG_SEN * temp_ist8310_data;
}

ist8310_error_e VerifyMegId(uint8_t* id) {
    rt_i2c_read_reg(IST8310_I2C_ADDR,IST8310_WHO_AM_I,id,1);
    if (*id != IST8310_WHO_AM_I_VALUE) {
        return MEG_ID_ERROR;
        LOG_E("no sensor\n");
    } else {
        return IST8310_NO_ERROR;
    }
}

void IST8310_INIT(ist8310_data_t* ist8310_data) {
    rt_memset(ist8310_data, 0, sizeof(ist8310_data_t));

    ist8310_data->ist8310_error = IST8310_NO_ERROR;

    // 把磁力计重启
    rt_pin_write(IST8310_RESET_PIN, PIN_LOW);
    HAL_Delay(50);
    rt_pin_write(IST8310_RESET_PIN, PIN_HIGH);
    HAL_Delay(50);

    

    // 基础配置
    rt_uint8_t tmp=0;
    // 进行初始化配置写入并检查是否写入成功,这里用循环把最上面初始化数组的东西都写进去
    for (uint8_t i = 0; i < IST8310_WRITE_REG_NUM; i++)
    { 
        // 写入配置,写一句就读一下看看ist8310是否仍然在线
        rt_i2c_write_reg(IST8310_I2C_ADDR, ist8310_write_reg_data_error[i][0], &ist8310_write_reg_data_error[i][1], 1);
        rt_thread_mdelay(1);
        rt_i2c_read_reg(IST8310_I2C_ADDR, ist8310_write_reg_data_error[i][0], &tmp, 1); // 读回自身id
        rt_thread_mdelay(1);
        if (tmp != ist8310_write_reg_data_error[i][1])
        {
                ist8310_data->ist8310_error = ist8310_write_reg_data_error[i][2];
                LOG_E("ist8310 init error, code %d", ist8310_write_reg_data_error[i][2]); // 掉线/写入失败/未知错误,会返回对应的错误码
        }
    }

    //ist8310_data->ist8310_error = VerifyMegId(&ist8310_data->chip_id);

}

int ist8310_init(void)
{

    /* 查找I2C总线设备，获取I2C总线设备句柄 */
    i2c3_bus = (struct rt_i2c_bus_device *)rt_device_find(IST8310_I2C_BUS_NAME);

    if (i2c3_bus == RT_NULL)
    {
        
        LOG_E("can't find %s device!\n", IST8310_I2C_BUS_NAME);
    }
    else
    {
        ist8310_data.ist8310_error = ist8310_no_init;

        IST8310_INIT(&ist8310_data);

        if (ist8310_data.ist8310_error == IST8310_NO_ERROR)
        {
            LOG_D("IST8310 Init sucess!!!\r\n");
        }

    }

    return RT_EOK;
}
INIT_ENV_EXPORT(ist8310_init);

